#include <omp.h>
#include <stdio.h>

int data0 = 0, data1 = 0;
int flag = 0;

int main() {
    #pragma omp parallel num_threads(3)
    {
        int thread_num = omp_get_thread_num();

        if (thread_num == 0) {
            // 线程 0 写入 data0 并更新 flag
            printf("Thread %d: Initial data0 is %d\n", thread_num, data0);
            data0 = 17;
            printf("Thread %d: Setting data0 to 17\n", thread_num);
            #pragma omp flush
            printf("Thread %d: Flushed data0\n", thread_num);
            #pragma omp atomic update
            flag++;
            printf("Thread %d: Incremented flag to %d\n", thread_num, flag);
        } else if (thread_num == 1) {
            // 线程 1 等待 flag 变为 1
            int flag_val = 0;
            while (flag_val < 1) {
                #pragma omp atomic read
                flag_val = flag;
                if (flag_val < 1) {
                    printf("Thread %d: Waiting for flag to become 1 (current flag: %d)\n", thread_num, flag_val);
                }
            }
            printf("Thread %d: Flag is now 1, data0 is %d\n", thread_num, data0);
            data1 = 42;
            printf("Thread %d: Setting data1 to 42\n", thread_num);
            #pragma omp flush(data1)
            printf("Thread %d: Flushed data1\n", thread_num);
            #pragma omp atomic update
            flag++;
            printf("Thread %d: Incremented flag to %d\n", thread_num, flag);
        } else if (thread_num == 2) {
            // 线程 2 等待 flag 变为 2
            int flag_val = 0;
            while (flag_val < 2) {
                #pragma omp atomic read
                flag_val = flag;
                if (flag_val < 2) {
                    printf("Thread %d: Waiting for flag to become 2 (current flag: %d)\n", thread_num, flag_val);
                }
            }
            #pragma omp flush(data0, data1)
            printf("Thread %d: Flushed data0 and data1\n", thread_num);
            printf("Thread %d: data0 is %d, data1 is %d\n", thread_num, data0, data1);
        }
    }

    return 0;
}
